package com.chrhc.projects.cpub.gen.codegenerate;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

import com.chrhc.projects.cpub.gen.def.CodeResourceUtil;
import com.chrhc.projects.cpub.gen.def.FtlDef;
import com.chrhc.projects.cpub.gen.model.ModelGenerateCodeLogic;
import com.chrhc.projects.cpub.gen.util.CreateBean;
import com.chrhc.projects.cpub.gen.xml.IbatisConfigBean;
import com.chrhc.projects.cpub.gen.xml.IbatisConfigColumn;
import com.chrhc.projects.cpub.gen.xml.IbatisConfigTableBean;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class GenerateCode
{
    // private static final Log log = LogFactory.getLog(GenerateCode.class);
    private static final Logger log = Logger.getLogger(GenerateCode.class);
    
    public static String FREEMARKER_CLASSPATH = "template";
    
    // public static String PROJECT_CLASS_ROOT_PATH = GenerateCode.class.getClassLoader().getResource("").getPath();
    public static String PROJECT_CLASS_ROOT_PATH = System.getProperty("user.dir");
    
    public String fileDir = null;// "test/file/"
    
    private String fileName = null;// www.ftl
    
    private static String url = CodeResourceUtil.URL;
    
    private static String username = CodeResourceUtil.USERNAME;
    
    private static String passWord = CodeResourceUtil.PASSWORD;
    
    private static String buss_package = CodeResourceUtil.bussiPackage;
    
    private static String projectPath = getProjectPath();
    
    private Map freemarkContext = new HashMap();// 存放freemark中的内容
    
    private static IbatisConfigBean ibatisConfig;
    
    public GenerateCode()
    {
    
    }
    
    public GenerateCode(IbatisConfigBean ibatisConfig)
    {
        log.debug("GenerateCode construct");
        this.ibatisConfig = ibatisConfig;
        log.debug("GenerateCode construct22");
    }
    
    public void codeGenerateByIbatisConfig()
        throws SQLException, IOException, TemplateException
    {
        log.debug(" codeGenerateByIbatisConfig start...");
        // String targetPackage = ibatisConfig.getModelTargetPackage();
        // String targetProject = ibatisConfig.getTargetProject();
        
        String path = System.getProperty("user.dir");
        // String targetPackageMk = path + "/src/main/java/" + targetPackage.replaceAll("\\.", "/");
        // String targetPackageMk = path + "/" + targetProject + "/" + targetPackage.replaceAll("\\.", "/");
        
        String modelMk = path + "/" + ibatisConfig.getModelTargetProject() + "/"
            + ibatisConfig.getModelTargetPackage().replaceAll("\\.", "/");
        String serviceMk = path + "/" + ibatisConfig.getServiceTargetProject() + "/"
            + ibatisConfig.getServiceTargetPackage().replaceAll("\\.", "/");
        String controlMk = path + "/" + ibatisConfig.getControlTargetProject() + "/"
            + ibatisConfig.getControlTargetPackage().replaceAll("\\.", "/");
        String jsMk = path + "/" + CodeResourceUtil.web_root_package_js;
        String htmlMk = path + "/" + CodeResourceUtil.web_root_package;
        log.debug("serviceMk" + serviceMk);
        log.debug("controlMk" + controlMk);
        // System.out.println("targetPackageMk=" + targetPackageMk);
        CreateBean createBean = new CreateBean();
        createBean.setMysqlInfo(ibatisConfig.getConnectionURL(), ibatisConfig.getUserId(), ibatisConfig.getPassword());
        String connectUrl = ibatisConfig.getConnectionURL();
        
        CodeResourceUtil.DATABASE_NAME = parserConnectUrlToDataBase(connectUrl);
        List<IbatisConfigTableBean> tableList = ibatisConfig.getTableList();
        String tableName;
        String domainObjectName;
        String content;
        String targetFileName = null;
        File packageMk = null;
        File targetFile = null;
        String entityPackage = null;
        String leafEntityPackage = null;
        String codeName = null;
        StringBuffer data;
        String targetPackageMk = path + "/" + ibatisConfig.getModelTargetProject() + "/"
            + ibatisConfig.getModelTargetPackage().replaceAll("\\.", "/");
        checkMk(targetPackageMk);
        targetPackageMk = path + "/" + ibatisConfig.getServiceTargetProject() + "/"
            + ibatisConfig.getServiceTargetPackage().replaceAll("\\.", "/");
        checkMk(targetPackageMk);
        targetPackageMk = path + "/" + ibatisConfig.getControlTargetProject() + "/"
            + ibatisConfig.getControlTargetPackage().replaceAll("\\.", "/");
        checkMk(targetPackageMk);
        
        for (IbatisConfigTableBean table : tableList)
        {
            tableName = table.getTableName();
            domainObjectName = table.getDomainObjectName();
            entityPackage = table.getEntityPackage();
            leafEntityPackage = table.getControllerMatchUrl();
            
            codeName = table.getTitle();
            // System.out.println("content::" + content);
            // targetFileName = targetPackageMk + "/" + domainObjectName + ".java";
            // packageMk = new File(targetPackageMk);
            // targetFile = new File(targetFileName);
            
            // Map colsMap = (Map)map.get("colsMap");
            // List<IbatisConfigColumn> cols = table.getColumns();
            Map<String, IbatisConfigColumn> cols = table.getColumnsMap();
            content = ModelGenerateCodeLogic.getBeanFeilds(tableName, cols, createBean.getColumnDatas(tableName));
            
            /*
             * if (!packageMk.exists()) { packageMk.mkdirs(); }
             */
            
            String modelImport = ModelGenerateCodeLogic.ModeImport(content);
            freemarkContext.put("modelImport", modelImport);
            freemarkContext.put("modelColContent", content);
            
            String className = domainObjectName;
            String lowerName = className.substring(0, 1).toLowerCase() + className.substring(1, className.length());
            
            // String srcPath = projectPath + CodeResourceUtil.source_root_package + "\\";
            // String srcPath = projectPath + targetProject + "\\";
            
            // String pckPath = srcPath + CodeResourceUtil.bussiPackageUrl + "\\";
            
            // String webPath = projectPath + CodeResourceUtil.web_root_package +
            // "\\view\\" + CodeResourceUtil.bussiPackageUrl + "\\";
            String webPath =
                projectPath + CodeResourceUtil.web_root_package + "\\" + CodeResourceUtil.bussiPackageUrl + "\\";
                
            // String beanPath = entityPackage + "\\" + "model\\" + className + ".java";
            String beanPath = "\\" + className + ".java";
            // String mapperPath = "dao\\" + entityPackage + "\\" + className + "Dao.java";
            // String servicePath = entityPackage + "\\" + "service\\" + className + "ServiceImpl.java";
            String servicePath = "\\" + className + "ServiceImpl.java";
            String iservicePath = "\\" + className + "ServiceI.java";
            // String controllerPath = entityPackage + "\\" + "web\\" + className + "Controller.java";//
            // controller这里叫web
            String controllerPath = "\\" + className + "Controller.java";// controller这里叫web
            String sqlMapperPath = "mapper\\" + entityPackage + "\\" + className + "Mapper.xml";
            webPath = webPath + entityPackage + "\\";
            
            String webJsPath =
                projectPath + CodeResourceUtil.web_root_package_js + "\\" + CodeResourceUtil.bussiPackageUrl + "\\";
            webJsPath = webJsPath + entityPackage + "\\";
            
            String jspPath = "\\" + entityPackage + "\\" + lowerName + ".jsp";
            // String jsPath = "page-" + lowerName + ".js";
            
            String jsPath = "\\" + entityPackage + "\\" + className.toLowerCase() + ".js";
            String indexHtmlPath = "\\" + entityPackage + "\\" + leafEntityPackage + "\\" + "index.html";
            
            freemarkContext.put("curDate", new Date());
            freemarkContext.put("author", CodeResourceUtil.AUTHOR);
            freemarkContext.put("version", CodeResourceUtil.VARSION);
            freemarkContext.put("className", className);
            freemarkContext.put("lowerName", lowerName);
            freemarkContext.put("codeName", codeName);
            freemarkContext.put("tableName", tableName);
            freemarkContext.put("bussPackage", buss_package);
            freemarkContext.put("bussPackageJsp", buss_package.replace(".", "/"));
            freemarkContext.put("entityPackage", entityPackage);
            freemarkContext.put("leafEntityPackage", leafEntityPackage);
            freemarkContext.put("keyType", FtlDef.KEY_TYPE_01);
            freemarkContext.put("modelPackage", ibatisConfig.getModelTargetPackage());
            /*
             * try { freemarkContext.put("feilds", createBean.getBeanFeilds(tableName)); } catch (Exception e) {
             * e.printStackTrace(); }
             */
            
            try
            {
                Map sqlMap = createBean.getAutoCreateSql(tableName);
                freemarkContext.put("columnDatas", createBean.getColumnDatas(tableName));
                freemarkContext.put("SQL", sqlMap);
            }
            catch (Exception e)
            {
                e.printStackTrace();
                return;
            }
            log.debug(" table generateFile tableName:" + tableName);
            // generateFile(freemarkContext, "IbatisEntityTemplate.ftl", pckPath, beanPath);
            generateFile(freemarkContext, "IbatisEntityTemplate.ftl", modelMk, beanPath);
            if (table.getEnableGenerateService() != null && table.getEnableGenerateService().equals("true"))
            {
                generateFile(freemarkContext, "IServiceTemplate.ftl", serviceMk, iservicePath);//
                generateFile(freemarkContext, "ServiceTemplate.ftl", serviceMk, servicePath);//
            }
            if (table.getEnableGenerateController() != null && table.getEnableGenerateController().equals("true"))
            {
                generateFile(freemarkContext, "ControllerTemplate.ftl", controlMk, controllerPath);
            }
            if (table.getEnableGenerateView() != null && table.getEnableGenerateView().equals("true"))
            {// 是否生成前端文件
                generateFile(freemarkContext, "JsTemplate.ftl", jsMk, jsPath);
                generateFile(freemarkContext, "IndexHtmlTemplate.ftl", htmlMk, indexHtmlPath);
            }
            
            // generateFile(freemarkContext, "jsTemplate.ftl", webJsPath, jsPath);
        }
    }
    
    private void checkMk(String targetPackageMk)
    {
        File packageMk = new File(targetPackageMk);
        if (!packageMk.exists())
        {
            packageMk.mkdirs();
        }
    }
    
    private String parserConnectUrlToDataBase(String url)
    {
        // jdbc:mysql://localhost:3308/jeecg
        if (url != null)
        {
            if (url.indexOf("?") > 0)
            {
                int len = url.indexOf("?");
                url = url.substring(0, len);
            }
            int start = url.lastIndexOf("/");
            String database = url.substring(start + 1);
            return database;
        }
        return null;
    }
    
    /**
     * 
     * @param tableName
     * @param codeName
     * @param entityPackage 实体包
     * @param keyType
     * @throws TemplateException
     * @throws IOException
     */
    public void codeGenerate(String tableName, String codeName, String entityPackage, String keyType,
        String leafEntityPackage, String author, String version)
            throws IOException, TemplateException
    {
        CreateBean createBean = new CreateBean();
        createBean.setMysqlInfo(url, username, passWord);
        
        String className = createBean.getTablesNameToClassName(tableName);
        String lowerName = className.substring(0, 1).toLowerCase() + className.substring(1, className.length());
        
        String srcPath = projectPath + CodeResourceUtil.source_root_package + "\\";
        
        String pckPath = srcPath + CodeResourceUtil.bussiPackageUrl + "\\";
        
        // String webPath = projectPath + CodeResourceUtil.web_root_package +
        // "\\view\\" + CodeResourceUtil.bussiPackageUrl + "\\";
        String webPath =
            projectPath + CodeResourceUtil.web_root_package + "\\" + CodeResourceUtil.bussiPackageUrl + "\\";
            
        String modelPath = "page\\" + entityPackage + "\\" + className + "Page.java";
        String beanPath = "entity\\" + entityPackage + "\\" + className + ".java";
        String mapperPath = "dao\\" + entityPackage + "\\" + className + "Dao.java";
        String servicePath = entityPackage + "\\" + "service\\" + className + "ServiceImpl.java";
        String iservicePath = entityPackage + "\\" + "service\\" + className + "ServiceI.java";
        String controllerPath = entityPackage + "\\" + "web\\" + className + "Controller.java";// controller这里叫web
        String sqlMapperPath = "mapper\\" + entityPackage + "\\" + className + "Mapper.xml";
        webPath = webPath + entityPackage + "\\";
        
        String webJsPath =
            projectPath + CodeResourceUtil.web_root_package_js + "\\" + CodeResourceUtil.bussiPackageUrl + "\\";
        webJsPath = webJsPath + entityPackage + "\\";
        
        String jspPath = lowerName + ".jsp";
        String jsPath = "page-" + lowerName + ".js";
        
        freemarkContext.put("curDate", new Date());
        freemarkContext.put("author", author);
        freemarkContext.put("version", version);
        freemarkContext.put("className", className);
        freemarkContext.put("lowerName", lowerName);
        freemarkContext.put("codeName", codeName);
        freemarkContext.put("tableName", tableName);
        freemarkContext.put("bussPackage", buss_package);
        freemarkContext.put("bussPackageJsp", buss_package.replace(".", "/"));
        freemarkContext.put("entityPackage", entityPackage);
        freemarkContext.put("leafEntityPackage", leafEntityPackage);
        freemarkContext.put("keyType", keyType);
        try
        {
            freemarkContext.put("feilds", createBean.getBeanFeilds(tableName));
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        
        try
        {
            Map sqlMap = createBean.getAutoCreateSql(tableName);
            freemarkContext.put("columnDatas", createBean.getColumnDatas(tableName));
            freemarkContext.put("SQL", sqlMap);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return;
        }
        
        generateFile(freemarkContext, "IServiceTemplate.ftl", pckPath, iservicePath);//
        generateFile(freemarkContext, "ServiceTemplate.ftl", pckPath, servicePath);//
        generateFile(freemarkContext, "ControllerTemplate.ftl", pckPath, controllerPath);
        
        /*
         * CommonPageParser.WriterPage(context, "EntityTemplate.ftl", pckPath, beanPath);
         * CommonPageParser.WriterPage(context, "PageTemplate.ftl", pckPath, modelPath);
         * CommonPageParser.WriterPage(context, "DaoTemplate.ftl", pckPath, mapperPath);
         * CommonPageParser.WriterPage(context, "ServiceTemplate.ftl", pckPath, servicePath);
         * CommonPageParser.WriterPage(context, "MapperTemplate.xml", pckPath, sqlMapperPath);
         * CommonPageParser.WriterPage(context, "ControllerTemplate.ftl", pckPath, controllerPath);
         * 
         * CommonPageParser.WriterPage(context, "jspTemplate.ftl", webPath, jspPath);
         * CommonPageParser.WriterPage(context, "jsTemplate.ftl", webJsPath, jsPath);
         */
        
        log.info("----------------------------代码生成完毕---------------------------");
    }
    
    public static Configuration getConfiguration()
        throws IOException
    {
        
        // System.out.println(getClass().getClassLoader().getResource("").getPath());
        // System.out.println(System.getProperty("user.dir"));
        Configuration cfg = new Configuration();
        // cfg.setClassForTemplateLoading(getClass(),"template2");
        cfg.setDirectoryForTemplateLoading(new File(PROJECT_CLASS_ROOT_PATH + "/" + FREEMARKER_CLASSPATH));
        cfg.setLocale(Locale.CHINA);
        cfg.setDefaultEncoding("UTF-8");
        return cfg;
    }
    
    public static void generateFile(Map context, String templateModeFileName, String targetPath, String targetFileName)
        throws IOException, TemplateException
    {
        // String fileDir = "test/file/";
        String fileNamePath = targetPath + targetFileName;
        Template template = getConfiguration().getTemplate(templateModeFileName);
        log.debug("targetPath==" + targetPath);
        // FileUtils.forceMkdir(new File(targetPath + "/"));
        File f = new File(fileNamePath);
        // f.getParent();
        // f.getParentFile().mkdirs();
        FileUtils.forceMkdir(f.getParentFile());
        Writer out = new OutputStreamWriter(new FileOutputStream(fileNamePath), "utf-8");
        template.process(context, out);
        out.close();
    }
    
    public static String getProjectPath()
    {
        String path = System.getProperty("user.dir").replace("\\", "/") + "/";
        return path;
    }
    
    /*
     * public static void main(String args[]) { System.out.println(GenerateCode.PROJECT_CLASS_ROOT_PATH);
     * System.out.println(GenerateCode.getProjectPath()); System.out.println("UUID.randomUUID().toString()==" +
     * UUID.randomUUID().toString()); String url =
     * "jdbc:mysql://localhost:3306/flowtest?useUnicode=true&amp;characterEncoding=utf-8"; GenerateCode code = new
     * GenerateCode(); System.out.println(code.parserConnectUrlToDataBase(url)); }
     */
    
}
